import {central,peripheral} from '../../../hos/ble.js';                           /*app底层蓝牙接口调用*/
import {os} from '../../../hos/os.js';                                         	  /*app底层接口调用*/
import {util} from './util.js';                                                   /*公共工具类js*/
/**
 * 监听方法，由于底层移除方法，所以回调函数不可用匿名函数
 */
let servicesArr = ['FEE7','FFF0','FEBA'];//蓝牙设备主 service 的 uuid 列表
class Bluetooth{
    constructor(){
		this.deviceId = "";//设备id
	    this.online = false;//这边连接状态
	    this.connectPacket = {};//连接设备包（包含设备所有信息）
	    //服务信息//特征值
	    this.serviceObj = { service: {}, characteristicsObj: {} };
        //连接超时定义
        this.connectTimeoutObj={
            timeoutId:null,//连接超时定时器
            timeout:60000,//超时默认为20秒
        }
    }

    /**
     * 设备初始化
     */
    init(){
    }

    /**
     * 获取本机蓝牙适配器状态
     */
    static getBluetoothAdapterState(){
        return central.isPoweredOn();
    }

    /**
     * 开始搜寻附近的蓝牙外围设备
     */
    startBluetoothDevices(notificationInterval=0){
        central.scan(null,notificationInterval);
    }

    /**
     * 停止搜寻附近的蓝牙外围设备
     * 注意：如果设备断开且开启了监听事件，则不能停止扫描
     * flag: 1直接断开  不传值则需判断监听事件
     */
    stopBluetoothDevices(flag){
        if(flag==1 || !this.addDisconnectObserverFun || (this.addDisconnectObserverFun&&this.online)){
            this.closeOnBluetoothDeviceFound();//关闭监听寻找到新设备的事件
            central.stopScan();
        }
    }

    /**
     * 获取所有已发现的蓝牙设备
     * option:选项指定某种状态的设备，缺省返回所有状态的外设
     * 		option 结构:{"state":"disconnected" | "connecting" | "connected" | "disconnecting"}
     */
    getBluetoothDevices(callback){
    	let bluetoothDevices=central.peripherals();
    	callback(Bluetooth.packagingScanDevice(bluetoothDevices));
    }

    /**
     * 监听寻找到新设备的事件
     */
    onBluetoothDeviceFound(callback){
        this.addDiscoverObserverFun=function(res){
            callback(Bluetooth.packagingScanDevice([res.data]));
        }
        central.addDiscoverObserver(this.addDiscoverObserverFun,this);
    }

    /**
     * 关闭监听寻找到新设备的事件
     */
    closeOnBluetoothDeviceFound(){
        central.removeDiscoverObserver(this.addDiscoverObserverFun);
    }

    /**
     * 连接低功耗蓝牙设备
     */
    createBLEConnection(callback){
        let _this=this,
            resMsg={retCode:0,res:{}};//返回参数
        _this.addConnectObserverFun=function(res){//连接回调方法
            resMsg={retCode:0,res:{}};//返回参数
            //监听设备连接上状态事件,由于有多个设备，所以需判断是否是自己的设备
            if(res.data.uuid==_this.connectPacket.uuid){//已连接上
                console.log('已连接上');
                central.removeConnectObserver(_this.addConnectObserverFun);//连接上了需要断开连接上监听事件
                //监听服务service方法
                _this.addDiscoverServicesObserverFun=function(res){
                    console.log('监听服务service方法',JSON.stringify(res));
                    let services=res.data.services;//服务uuid
                    //检索有用的服务通道
                    for(let item in _this.connectPacket.serviceuuid){
                        for(let i=0;i<services.length;i++){
                            if(_this.connectPacket.serviceuuid[item]==services[i]){
                                _this.serviceObj.service[item]=services[i];
                            }
                        }
                    }

                    //获取蓝牙设备所有 characteristic（特征值）
                    peripheral.addDiscoverCharacteristicsObserver(_this.connectPacket, _this.addDiscoverCharacteristicsObserverFun, _this);
                    for(let item in _this.serviceObj.service){
                        //开启扫描外设的服务，只有打开这个才能获取蓝牙设备characteristic（特征值）
                        peripheral.discoverCharacteristics(_this.connectPacket,_this.serviceObj.service[item]);
                    }
                }
                //characteristic（特征值）方法
                _this.addDiscoverCharacteristicsObserverFun=function(res){
                    console.log('characteristic（特征值）方法',JSON.stringify(res));
                    let characteristics=res.data.characteristics;
                    for(let item in _this.connectPacket.characteristicObj){
                        let characteristic=_this.connectPacket.characteristicObj[item];
                        for(let i=0;i<characteristics.length;i++){
                            if(characteristic.read==characteristics[i]){
                                if(!_this.serviceObj.characteristicsObj[item]) _this.serviceObj.characteristicsObj[item]={};
                                _this.serviceObj.characteristicsObj[item].read=characteristics[i];
                            }
                            if(characteristic.write==characteristics[i]){
                                if(!_this.serviceObj.characteristicsObj[item]) _this.serviceObj.characteristicsObj[item]={};
                                _this.serviceObj.characteristicsObj[item].write=characteristics[i];
                            }
                            if(characteristic.indicate==characteristics[i]){
                                console.log('characteristic（特征值）方法indicate',characteristics[i]);
                                if(!_this.serviceObj.characteristicsObj[item]) _this.serviceObj.characteristicsObj[item]={};
                                _this.serviceObj.characteristicsObj[item].indicate=characteristics[i];
                            }
                            if(characteristic.notify==characteristics[i]){
                                console.log('characteristic（特征值）方法notify',characteristics[i]);
                                if(!_this.serviceObj.characteristicsObj[item]) _this.serviceObj.characteristicsObj[item]={};
                                _this.serviceObj.characteristicsObj[item].notify=characteristics[i];
                            }
                        }

                        //判断回来的特征值
                        if(res.data.service==_this.connectPacket.serviceuuid[item]){
                            _this.connectPacket.characteristicObj[item].flag=true;
                        }

                    }

                    let characteristicFlag=true;
                    for(let item in _this.connectPacket.characteristicObj){//判断所有是特征值都回来
                        if(!_this.connectPacket.characteristicObj[item].flag){
                            characteristicFlag=false;
                            break;
                        }
                    }

                    if(characteristicFlag){//多个特征值的情况，需等所有值回来才算连接成功
                        //连接设备成功,清除监听方法
                        peripheral.removeDiscoverServicesObserver(_this.connectPacket,_this.addDiscoverServicesObserverFun);//service(服务)
                        peripheral.removeDiscoverCharacteristicsObserver(_this.connectPacket,_this.addDiscoverCharacteristicsObserverFun);//characteristic（特征值）
                        //设备连接连路打通,将数据回调
                        clearTimeout(_this.connectTimeoutObj.timeoutId);//清除连接超时定时器
                        _this.online = true;//设备在线
                        resMsg.retCode=1;
                        callback(resMsg);
                    }

                }
                //获取蓝牙设备所有 service（服务）
                peripheral.addDiscoverServicesObserver(_this.connectPacket, _this.addDiscoverServicesObserverFun, _this);
                //开启扫描外设的服务，只有打开这个才能获取蓝牙设备所有 service（服务）
                peripheral.discoverServices(_this.connectPacket);
            }
        }

        central.addConnectObserver(_this.addConnectObserverFun,_this);//连接设备监听事件
        //_this.closeBLEConnection();//断开上次连接的，防止重复连接,。。。有时会影响连接,后续优化
        central.connect(_this.connectPacket);//连接设备 通过扫描到的uuid连接
        if(_this.connectTimeoutObj.timeoutId) clearTimeout(_this.connectTimeoutObj.timeoutId);//清除定时器
        //连接超时
        _this.connectTimeoutObj.timeoutId=setTimeout(function(){
            //清除监听方法
            peripheral.removeDiscoverServicesObserver(_this.connectPacket,_this.addDiscoverServicesObserverFun);//service(服务)
            peripheral.removeDiscoverCharacteristicsObserver(_this.connectPacket,_this.addDiscoverCharacteristicsObserverFun);//characteristic（特征值）
            central.removeConnectObserver(_this.addConnectObserverFun);//连接上了需要断开连接上监听事件
            clearTimeout(_this.connectTimeoutObj.timeoutId);
            //os.makeToast("连接超时",2000);
            _this.closeBLEConnection();//断开上次连接的
            _this.online = false;//设备断开
            //超时处理
            resMsg.retCode=0;
            callback(resMsg);
        },_this.connectTimeoutObj.timeout);
    }

    /**
     * 断开与低功耗蓝牙设备的连接
     */
    closeBLEConnection(){
        this.stopBluetoothDevices(1);//停止搜寻附近的蓝牙外围设备
        central.cancelConnect(this.connectPacket,true);//断开设备
        this.closeReadyData();
    }

    /**
     * 监听低功耗蓝牙设备的特征值的二进制数据值
     * 注：如果有读取数据通道则读取，有监听通道则开启监听通道，安卓的一些机型readValue和setNotifyValue要队列下发，否则会失败
     * type:启用读取数据的通道
     * callback:监听数据回调
     */
    readyData(type,callback){
        let _this=this;
        if(_this.serviceObj.characteristicsObj[type].read){//读取数据
            peripheral.readValue(_this.connectPacket, _this.serviceObj.service[type], _this.serviceObj.characteristicsObj[type].read);
        }
        //检索有用的服务通道
        let uuid=_this.serviceObj.characteristicsObj[type].indicate ? _this.serviceObj.characteristicsObj[type].indicate:_this.serviceObj.characteristicsObj[type].notify;
        if(uuid){//监听数据
            peripheral.setNotifyValue(_this.connectPacket, _this.serviceObj.service[type], uuid, true);
        }
        if(callback){
            //监听数据回调方法
            _this.addUpdateValueObserverFun=function(res){
                callback(res);
            }
            peripheral.addUpdateValueObserver(_this.connectPacket,_this.addUpdateValueObserverFun,_this);
        }
    }

    /**
     *
     */

    /**
     * 关闭监听低功耗蓝牙设备的特征值的二进制数据值
     */
    closeReadyData(){
        if(this.addUpdateValueObserverFun) peripheral.removeUpdateValueObserver(this.connectPacket,this.addUpdateValueObserverFun);//断开监听低功耗蓝牙设备的特征值的二进制数据值
    }

    /**
     * 向低功耗蓝牙设备特征值中写入二进制数据
     * type:启用写数据的通道
     * value:下发值
     * callback:下发回调函数
     */
    sendData(type,value,callback){
        peripheral.writeValue(this.connectPacket, this.serviceObj.service[type], this.serviceObj.characteristicsObj[type].write, value);
    }

    /**
     * 监听设备断开/连接状态
     * 监听设备,重新连接设备(凡是调用监听事件的，页面卸载时必须停止扫描)
     */
    onWXDeviceBindStateChange(callback){
        let _this=this;
        _this.addDisconnectObserverFun=function(res){
            if(res.data.uuid==_this.connectPacket.uuid){
                _this.online=false;
                if(callback) callback();//监听回调
                //重新监听设备连接事件
                _this.startBluetoothDevices();//开启扫描
                _this.onBluetoothDeviceFound(function(devices){//监听设备
                    for(let i=0;i<devices.length;i++){
                        if(devices[i].uuid==_this.connectPacket.uuid){//找到设备
                            _this.createBLEConnection(function(res){//重新连接设备
                                if(callback) callback();//监听回调
                                _this.stopBluetoothDevices(1);//停止扫描
                            });
                        }
                    }
                });
            }
        }
        central.addDisconnectObserver(_this.addDisconnectObserverFun,_this);//监听设备断开事件
    }

    /**
     * 关闭蓝牙模块
     * false:依然缓存外设信息
     * true:从内存移除所有设备，清空外设列表
     */
    closeBluetoothAdapter(isClean){
        this.stopBluetoothDevices(1);//停止搜寻附近的蓝牙外围设备
        //清除所有监听事件
        if(this.addConnectObserverFun) central.removeConnectObserver(this.addConnectObserverFun);//连接上了需要断开连接上监听事件
        if(this.addDiscoverServicesObserverFun) peripheral.removeDiscoverServicesObserver(this.connectPacket,this.addDiscoverServicesObserverFun);//service(服务)
        if(this.addDiscoverCharacteristicsObserverFun) peripheral.removeDiscoverCharacteristicsObserver(this.connectPacket,this.addDiscoverCharacteristicsObserverFun);//characteristic（特征值）
        this.closeReadyData();
        if(this.addDisconnectObserverFun) central.removeDisconnectObserver(this.addDisconnectObserverFun);//断开监听低功耗蓝牙设备的断开事件
        if(this.connectTimeoutObj.timeoutId) clearTimeout(this.connectTimeoutObj.timeoutId);//清除定时器
        central.cancelAllConnect(isClean);
    }

    /**
     * 引入了字符串补全长度的功能 len:补全后长度
     * str1:需要补全的字符串
     * str2：补全替代字符串
     */
    static padStartPack(len, str1, str2) {
        let str = str1;
        for (let i = str1.length; i < len;) {
            str = str2 + str;
            i = i + str2.length;
        }
        str = str.substring(str.length - len, len + 1);
        return str;
    }

    /**
     * 校验服务通道
     * arr：校验数组
     * flag:服务通道标志
     */
    static verifyServiceUUID(arr, flag) {
        let verifyResult = false;
        for (let i = 0; i < arr.length; i++) {//再加一个判断
            if (arr[i] == flag) {//判断是否有交互通道
                verifyResult = true;
                break;
            }
        }
        return verifyResult;
    }

    /**
     * 搜索到设备封装
     * res:设备列表
     */
    static packagingScanDevice(res){
        //console.log('扫描到设备',JSON.stringify(res));
	    let devicesList=res,
	    	devices=[];//二次封装
	    for (let j = 0; j < devicesList.length; j++) {
	    	let obj=devicesList[j];
	    	obj.advertisData=[];//广播内容数组

            let localName=obj.advData.localName ? obj.advData.localName : obj.name;//设备名字

            if(obj.advData.manufacturer && obj.advData.manufacturer!=''){//有广播内容
    	    	let manufacturerDataArr=obj.advData.manufacturer.slice('');//分割为数组
    	    	for(let i=0;i<manufacturerDataArr.length;){
    	    		let str=manufacturerDataArr[i]+manufacturerDataArr[i+1];
    	    		obj.advertisData.push(parseInt(str,16));
    	    		i+=2;
    	    	}
                let mfd5="";//设备名字
                obj.localName=localName;
    	    	if(obj.advertisData.length>6){
                    mfd5=obj.advData.manufacturer.substring(0,10);//截取前5字节
    	    	}

    	    	if ((obj.advertisData.length == 11) && (mfd5 == "0600fe0101")) {//恒诺泰
                    if(obj.advData.services && Bluetooth.verifyServiceUUID(obj.advData.services, "FEE7")){
        	    		let mfd6 = obj.advertisData.slice(-6);//蓝牙地址
                        if (mfd6[1] == 0xf0) { obj.type = "Bicycle"; }
                        else if (mfd6[1] == 0xf1) { obj.type = "Treadmill"; }
                        else if (mfd6[1] == 0xf2) { obj.type = "Stepper"; }
                        else if (mfd6[1] == 0xf3) { obj.type = "Dumbbell"; }
                        else if (mfd6[1] == 0xf4) { obj.type = "Abdominal"; }
                        else if (mfd6[1] == 0xf5) { obj.type = "EplMachine"; }
                        else if (mfd6[1] == 0xf6) { obj.type = "EplMachineBig"; }
                        else if (mfd6[1] == 0xf7) { obj.type = "Rope"; }
                        else if (mfd6[1] == 0xf9) { obj.type = "PowerPlate"; }
                        else if (mfd6[1] == 0xfa) { obj.type = "SmartPig"; }
                        else if (mfd6[1] == 0xfb) { obj.type = "PowerRoller"; }
                        else if (mfd6[1] == 0xfc) { obj.type = "RowingMachine"; }
                        else if (mfd6[1] == 0xfd) { obj.type = "Cycling"; }
                        else if (mfd6[1] == 0xfe) { obj.type = "Walkingpad"; }
                        else if (mfd6[1] == 0xe0) { obj.type = "Steelyard"; }
                        else if (mfd6[1] == 0xe4) { obj.type = "FasciaGun"; }

                        obj.company = Bluetooth.padStartPack(2, mfd6[0].toString(16), "0");//公司名称
                        obj.advertis = obj.advData.manufacturer.substring(10,23);//蓝牙地址
                        obj.serviceuuid = { all: "FEE7" };
                        obj.characteristicObj = { all: { read: "FEC9", write: "FEC7", indicate: "FEC8" } };//特征值判断uuid 不用启用的indicate,notify一定为空
                        devices.push(obj);
                        continue;
                    }
    	    	}else if (localName == "HBM_B3"){//恒诺泰手环 (领越电子)
                    if(obj.advertisData.length == 8){
                        obj.type='Smartband';
                        obj.company = "00";
                        obj.advertis = util.decimalismArrToHex(obj.advertisData.slice(-6).reverse());
                        obj.serviceuuid = { all: "0001" };
                        obj.characteristicObj = { all: { write: "0002", notify: "0003" } };//特征值判断uuid
                        devices.push(obj);
                        continue;
                    }
                }else if (localName == "Hnk_scales" && obj.advertisData.length==14) {//河马秤 (闪易)
                    let mfd6 = obj.advertisData.slice(-2).concat([0x01]).concat(obj.advertisData.slice(2,5));
                    obj.type = "Steelyard";
                    obj.company = "00";
                    obj.advertis = util.decimalismArrToHex(mfd6);
                    devices.push(obj);
                    continue;
                }else if (localName == "Hscales" && obj.advertisData.length == 13) {//闪易另一款
                    let flag=false;
                    for(let i=0;i<obj.advData.services.length;i++){
                        if(obj.advData.services[i]=='FFF0'){
                            flag=true;
                            break;
                        }
                    }
                    if(flag){
                        let mfd6 = [obj.advertisData[10], obj.advertisData[11], 0x01].concat(obj.advertisData.slice(0, 3));
                        obj.type = "Steelyard";
                        obj.company = "00";
                        obj.advertis = util.decimalismArrToHex(mfd6);
                        devices.push(obj);
                        continue;
                    }
                }

            }else{//没有广播内容
                if(localName=='ESLinker' || localName=='ESLinkerEx'){//立久佳
                    let flag=false;st
                    for(let i=0;i<obj.advData.services.length;i++){
                        if(obj.advData.services[i].toUpperCase()=='FFF0'){
                            flag=true;
                            break;
                        }
                    }
                    if(flag){
                        obj.localName=localName;
                        obj.type = "Treadmill";
                        obj.company='c4';
                        if(os.isAndroid()){
                            obj.advertis=obj.uuid.replace(/:/g, "");
                        }else{//后续可通过 FEE7的FEC9读取蓝牙地址
                            obj.advertis='c4f100000000';
                        }

                        obj.serviceuuid = { all: 'FFF0', blue:'FEE7' };
                        obj.characteristicObj = {all: { write: 'FFF2', notify: 'FFF1' }, blue: { read: 'FEC9' }};
                        devices.push(obj);
                        continue;
                    }
                }
            }
            // ++++[
            // console.log('ignore ble device:', obj.uuid);
            central.ignore(obj);
            // ]++++
	    }

	    return devices;
	}

}


//搜索到设备封装



export{Bluetooth}
